//
//  ViewController.m
//  AudioUnit2
//
//  Created by apple on 5/28/17.
//  Copyright © 2017 lzb.cn. All rights reserved.
//

#import "ViewController.h"
#import <AudioUnit/AudioUnit.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController (){
    @public
    AudioComponent _audioComponment;
    AudioComponentInstance _audioUint;
    AudioStreamBasicDescription _asbd;
    //播放音频队列
    AudioQueueRef _audioQueue;
    //音频缓存
    AudioQueueBufferRef _audioQueueBuffers[3];
    BOOL _audioQueueUsed[3];
    int _index;
}

@end

@implementation ViewController
//录音demo
- (void)viewDidLoad {
    [super viewDidLoad];

//    obj = self;
    // Do any additional setup after loading the view, typically from a nib.
    [self configAudio];
}

- (void)configAudio{
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
    [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
    UInt32 audioRouteOverride = 1;
    AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
                            sizeof(audioRouteOverride),
                            &audioRouteOverride);
    [[AVAudioSession sharedInstance] setActive:YES error:nil];
    
    OSStatus result = noErr;
    
    //创建AudioUnit
    AudioComponentDescription acd = {0};
    acd.componentType = kAudioUnitType_Output;
//    acd.componentSubType = kAudioUnitSubType_RemoteIO;
    acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
    acd.componentManufacturer = kAudioUnitManufacturer_Apple;
    acd.componentFlags = 0;
    acd.componentFlagsMask = 0;
    
    _audioComponment = AudioComponentFindNext(NULL, &acd);
    
    result = AudioComponentInstanceNew(_audioComponment, &_audioUint);
    if(result != noErr){
        NSLog(@"创建失败");
    }
    
    //设置参数属性
    UInt32 flagOne = 1;
    AudioUnitSetProperty(_audioUint,
                         kAudioOutputUnitProperty_EnableIO,
                         kAudioUnitScope_Input,
                         1,
                         &flagOne,
                         sizeof(flagOne));
    
    
    AudioStreamBasicDescription asbd ={0};
    asbd.mSampleRate = 8000;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = (kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked);
    asbd.mChannelsPerFrame = 1;
    asbd.mFramesPerPacket = 1;
    asbd.mBitsPerChannel = 16;
    asbd.mBytesPerFrame = asbd.mBitsPerChannel * asbd.mChannelsPerFrame / 8 ;
    asbd.mBytesPerPacket = asbd.mFramesPerPacket * asbd.mBytesPerFrame;
    asbd.mReserved = 0;
    //设置格式
    AudioUnitSetProperty(_audioUint, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &asbd, sizeof(asbd));
    
    AURenderCallbackStruct cb = {0};
    cb.inputProcRefCon = (__bridge void * _Nullable)(self);
    cb.inputProc = handleInputBuffer;
    
    //设置录制回调
    AudioUnitSetProperty(_audioUint, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, sizeof(cb));
    
    //初始化
    result = AudioUnitInitialize(_audioUint);
    if (result != noErr) {
        NSLog(@"创建失败");
        return;
    }
    AudioOutputUnitStart(_audioUint);
    
    //添加通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeAudioRoute:) name:AVAudioSessionRouteChangeNotification object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:nil];
    
    
    //使用AudioQueue播放
    _asbd.mSampleRate = 8000;
    _asbd.mFormatID = kAudioFormatLinearPCM;
    _asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    _asbd.mChannelsPerFrame = 1;
    _asbd.mFramesPerPacket = 1;
    _asbd.mBitsPerChannel = 16;
    _asbd.mBytesPerFrame = asbd.mBytesPerFrame;
    _asbd.mBytesPerPacket = asbd.mBytesPerPacket;
    //Creates a new playback audio queue object.
    AudioQueueNewOutput(&_asbd, BufferCallback, (__bridge void * _Nullable)(self), nil, nil, 0, &_audioQueue);
    
    
    //初始化音频缓冲区
    for (int i = 0; i < 3; i++) {
        //创建buffer
        result = AudioQueueAllocateBuffer(_audioQueue, 2048, &_audioQueueBuffers[i]);
        if (result != noErr) {
            NSLog(@"creat AudioQueue fail");
        }
        //初始化
        memset(_audioQueueBuffers[i]->mAudioData, 0, 2048);
    }
    //设置AudioQueue
    AudioQueueSetParameter(_audioQueue, kAudioQueueParam_Volume, 20.0);
}

static OSStatus handleInputBuffer(void *inRefCon,
                                  AudioUnitRenderActionFlags *ioActionFlags,
                                  const AudioTimeStamp *inTimeStamp,
                                  UInt32 inBusNumber,
                                  UInt32 inNumberFrames,
                                  AudioBufferList *ioData)
{
    ViewController *vc = (__bridge ViewController *)(inRefCon);
    
    AudioBufferList bufferList;
    bufferList.mNumberBuffers = 1;
    bufferList.mBuffers[0].mData = NULL;
    bufferList.mBuffers[0].mDataByteSize = 0;
//    [vc.lock lock];
    
    AudioUnitRender(vc->_audioUint, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
    
    //SInt16 *rece = (SInt16 *)bufferList.mBuffers[0].mData;
    
    void *data = malloc(bufferList.mBuffers[0].mDataByteSize);
    memcpy(data, bufferList.mBuffers[0].mData, bufferList.mBuffers[0].mDataByteSize);
    //play
    AudioQueueBufferRef audioBuffer = NULL;
    if (vc->_index == 2) {
        vc->_index = 0;
    }
    
    audioBuffer = vc->_audioQueueBuffers[vc->_index];
    vc->_index ++;
    audioBuffer->mAudioDataByteSize = bufferList.mBuffers[0].mDataByteSize;
    memset(audioBuffer->mAudioData, 0, bufferList.mBuffers[0].mDataByteSize);
    memcpy(audioBuffer->mAudioData, data, bufferList.mBuffers[0].mDataByteSize);
    
    AudioQueueEnqueueBuffer(vc->_audioQueue, audioBuffer, 0, NULL);
    free(data);
    
//    [vc.lock unlock];
    return noErr;
}

//AudioQueue回调
static void BufferCallback(void *inUserData, AudioQueueRef inAQ,
                           AudioQueueBufferRef buffer){
//    NSLog(@"播放回调");
//    ViewController *vc = (__bridge ViewController *)(inUserData);
//        for (int  i = 0;  i < 2048; i ++) {
//            if (buffer == vc-> _audioQueueBuffers[i]) {
//                
//            }
//        }
}

//改变audioRoute
- (void)changeAudioRoute:(NSNotification *)noti{
    if ([noti.userInfo[AVAudioSessionRouteChangeReasonKey] integerValue] ==
        AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { //拔出耳塞
        AudioOutputUnitStop(_audioUint);
        
    }else  if ([noti.userInfo[AVAudioSessionRouteChangeReasonKey] integerValue] ==
               AVAudioSessionRouteChangeReasonNewDeviceAvailable){
        for (AVAudioSessionPortDescription* desc in [[AVAudioSession sharedInstance].currentRoute outputs]) {
            if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])
                return;
        }
        AudioOutputUnitStop(_audioUint);
    }
}

- (void)handleInterruption:(NSNotification *)notification{
    
}
- (IBAction)didClickStartOrStop:(UIButton *)sender {
    
    if (sender.selected) {
        sender.selected = NO;
        
        //start
        //AudioOutputUnitStop(_audioUint);
        
        AudioQueuePause(_audioQueue);
    }else{
        sender.selected = YES;
        
        //start
        //AudioOutputUnitStart(_audioUint);
        
        AudioQueueStart(_audioQueue, NULL);
    }
    
}

- (IBAction)changeVPIO:(UISwitch *)sender {
    UInt32 echoCancellation;
    UInt32 size = sizeof(echoCancellation);
    AudioUnitGetProperty(_audioUint,
                                    kAUVoiceIOProperty_BypassVoiceProcessing,
                                    kAudioUnitScope_Global,
                                    0,
                                    &echoCancellation,
                                    &size);
    if (sender.isOn) {
        echoCancellation = 0;
    }else{
        echoCancellation = 1;
    }
    
    AudioUnitSetProperty(_audioUint,
                                    kAUVoiceIOProperty_BypassVoiceProcessing,
                                    kAudioUnitScope_Global,
                                    0,
                                    &echoCancellation,
                                    sizeof(echoCancellation));
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
